package com.iamteer.day17;

import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
双列集合：
--------| Map 存储的数据都是以键值对形式存在的，键不能重复，值可以
------------| HashMap	底层基于哈希表实现，
------------| TreeMap	底层基于红黑树数据结构实现，特点：对元素的键进行排序存储
------------| HashTable	底层基于哈希表实现，线程安全，效率低。


Map 方法：

	添加
		put(K key, V value);
		putAll(Map<? extends K, ? extends V> m);
	
	获取
		get(Object key);
		size();
		
	判断
		containsKey(Object key);
		containsValue(Object value);
		isEmpty();
		
	删除
		remove(Object key);
		clear();
		
	迭代：
		keySet();
		values();
		entrySet();
------------------------------------------------------------------------------------------------------		
1. HashMap
	往HashMap 添加元素的时候，先调用键的 hashCode 方法得到元素的哈希值，然后计算出元素在哈希表中的存储位置
	若位置目前为空，则直接存储元素到该位置；
	若位置已经存储了元素，则调用元素的 equals 方法判断是否为同一元素，如果不同，则存储，如果相同，则视为重复不存储。

2. TreeMap
	2.1 往TreeMap 添加元素时，若元素具备自然顺序，则按自然顺序存储
	2.2 往TreeMap 添加元素时，若元素不具备自然顺序，则需要键所属类必须实现 Comparable 接口，把键的比较规则定义在 CompareTo 方法上；
		或者在创建 TreeMap 对象的时候传入比较器。
	 
 */

class Human{
	int id;
	String name;
	public Human(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	@Override
	public String toString() {
		return "[编号：" + this.id + "姓名：" + this.name + "]";
	}
	
	//下面重写 equals 方法和 hashCode 方法，重新定义相同的标准
	@Override
	public boolean equals(Object obj) {
		Human human = (Human) obj;
		return this.id == human.id;
	}
	
	@Override
	public int hashCode() {
		return this.id;
	}
}

class Emp implements Comparable<Emp>{
	String name;
	int salary;
	public Emp(String name, int salary) {
		super();
		this.name = name;
		this.salary = salary;
	}
	
	@Override
	public String toString() {
		return "{姓名：" + this.name + "薪水：" + this.salary + "}";
	}
	
	@Override	//元素与元素之间的比较规则
	public int compareTo(Emp o) {
//		System.out.println(this.name + " ：" + emp.name);	//查看比较过程
		return this.salary - o.salary;
	}
}

class MyComparator implements Comparator<Emp>{
	@Override
	public int compare(Emp o1, Emp o2) {
		return o2.salary - o1.salary;
	}
}

public class LearnMap {

	public static void main(String[] args) {
//		mapMethods();	//演示 map 方法
//		testHashMap();	//演示 HashMap 方法
		testTreeMap();	//演示 TreeMap 方法
	}
	
	//演示 Map 的方法
	public static void mapMethods() {
		Map<String, String> map = new HashMap<String, String>();
		
		//----演示 put 方法
		map.put("汪峰", "章子怡");
		map.put("文章", "马伊琍");
		map.put("谢霆锋", "张柏芝");
		
		//返回该 key 之前对应的 Value 值（若之前没有则是 null）
		System.out.println(map.put("谢霆锋", "黄菲"));
		System.out.println(map);
		
		//----演示 putAll 方法
		Map<String, String> map2 = new HashMap<String, String>();
		map2.put("老公", "老婆");
		map2.put("公", "母");
		map.putAll(map2);
		System.out.println(map);
		
		//----演示 remove 方法
		System.out.println(map.remove("公"));	//返回该 Key 对应的 Value
		System.out.println(map);
		
		//----演示 clear 方法
//		map.clear();	//清空 map
//		System.out.println(map);
		
		//----演示 get 方法
		System.out.println(map.get("老公"));	//返回 key 对应的 value（不存在自然就是 null 了）
		//----演示 size 方法
		System.out.println(map.size());	//返回 map 的 key-value 对数
		
		//----演示 containsKey 方法
		System.out.println(map.containsKey("文章"));
		System.out.println(map.containsKey("章"));
		//----演示 containsValue 方法
		System.out.println(map.containsValue("老婆"));
		System.out.println(map.containsValue("婆"));
		
		//----演示 isEmpty 方法
		System.out.println(map.isEmpty());
//		map.clear();
//		System.out.println(map.isEmpty());
//		map.put(null, null);	//这样也非空
//		System.out.println(map.isEmpty());
		
		//----演示 keySet 方法（遍历方法一）
		Set<String> keys =  map.keySet();	//所有的键
		Iterator<String> iterator = keys.iterator();
		while (iterator.hasNext()) {
			String key = (String) iterator.next();
			System.out.println(key + "\t: " + map.get(key));
		}
		
		//----演示 values 方法（遍历方法二）
		Collection<String> values = map.values();	//所有的值
		Iterator<String> iterator2 = values.iterator();
		while (iterator2.hasNext()) {
			String value = (String) iterator2.next();
			System.out.println(value);
		}
		
		//----演示 entrySet 方法（遍历方法三）
		Set<Map.Entry<String, String>> entrys = map.entrySet();	//所有键值对
		Iterator<Map.Entry<String, String>> iterator3 = entrys.iterator();
		while (iterator3.hasNext()) {
			Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator3.next();
			System.out.println(entry.getKey() + "\t: " + entry.getValue());
		}
	}
	
	//演示 HashMap
	public static void testHashMap() {
		HashMap<Human, String> hashMap = new HashMap<Human, String>();
		hashMap.put(new Human(110, "狗娃"), "001");
		hashMap.put(new Human(220, "狗剩"), "002");
		hashMap.put(new Human(330, "铁蛋"), "003");
		hashMap.put(new Human(110, "狗娃"), "007");	//重写了 hashCode 方法，这会变成重复元素，会覆盖前面的
		
		System.out.println(hashMap);
	}

	//演示 TreeMap
	public static void testTreeMap() {
		 TreeMap<Character, Integer> treeMap = new TreeMap<Character, Integer>();
		 treeMap.put('E', 4);
		 treeMap.put('G', 8);
		 treeMap.put('C', 10);
		 treeMap.put('D', 2);
		 treeMap.put('F', 1);
		 
		 System.out.println(treeMap);
		 
//		 TreeMap<Emp, String> treeMap2 = new TreeMap<Emp, String>();	//CompareTo 定义了从小到大排
		 TreeMap<Emp, String> treeMap2 = new TreeMap<Emp, String>(new MyComparator());	//Comparator 定义了从大到小排
		 treeMap2.put(new Emp("冰冰", 2000), "001");
		 treeMap2.put(new Emp("家宝", 1000), "002");
		 treeMap2.put(new Emp("习总", 3000), "003");
		 treeMap2.put(new Emp("克强", 5000), "005");	
		 treeMap2.put(new Emp("才厚", 5000), "008");	//键相同，值被覆盖，所以会出现{姓名：克强薪水：5000}=008
		 
		 System.out.println(treeMap2);
	}
}
